package com.ruoyi.attendance.service.impl;

import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.concurrent.TimeUnit;

import com.ruoyi.attendance.domain.AttendanceRecord;
import com.ruoyi.attendance.domain.SignRecord;

import com.ruoyi.attendance.domain.UnsignedRecord;
import com.ruoyi.attendance.mapper.SignRecordMapper;
import com.ruoyi.attendance.mapper.UnsignedRecordMapper;
import com.ruoyi.attendance.service.IAttendanceRecordService;
import com.ruoyi.attendance.service.ISignRecordService;
import com.ruoyi.common.enums.AttendanceTime;
import com.ruoyi.common.enums.SignStatus;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.course.domain.CourseRecord;
import com.ruoyi.course.mapper.CourseRecordMapper;
import com.ruoyi.course.service.ICourseRecordService;
import com.ruoyi.course.service.ISelectCourseService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.apache.commons.beanutils.BeanUtils;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.stream.Collectors;

import org.springframework.stereotype.Service;
import com.ruoyi.attendance.mapper.AttendanceInfoMapper;
import com.ruoyi.attendance.domain.AttendanceInfo;
import com.ruoyi.attendance.service.IAttendanceInfoService;
import org.springframework.transaction.annotation.Transactional;


/**
 * 考勤记录Service业务层处理
 *
 * @author Weiney
 * @date 2025-03-01
 */
@Service
public class AttendanceInfoServiceImpl implements IAttendanceInfoService {
    private static final Logger log = LoggerFactory.getLogger(AttendanceInfoServiceImpl.class);
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    @Autowired
    private AttendanceInfoMapper attendanceInfoMapper;
    @Autowired
    private UnsignedRecordMapper unsignedRecordMapper;
    @Autowired
    private SignRecordMapper signRecordMapper;
    @Autowired
    private ICourseRecordService courseRecordService;
    @Autowired
    private IAttendanceInfoService attendanceInfoService;

    /**
     * 查询考勤记录
     *
     * @param attendanceId 考勤记录主键
     * @return 考勤记录
     */
    @Override
    public AttendanceInfo selectAttendanceInfoByAttendanceId(Long attendanceId) {
        return attendanceInfoMapper.selectAttendanceInfoByAttendanceId(attendanceId);
    }

    /**
     * 根据courseRecordId查询考勤记录
     *
     * @param courseRecordId course_record的主键
     * @return
     */
    @Override
    public AttendanceInfo selectAttendanceInfoByCourseRecordId(Long courseRecordId) {
        return attendanceInfoMapper.selectAttendanceInfoByCourseRecordId(courseRecordId);
    }

    /**
     * 查询考勤记录列表
     *
     * @param attendanceInfo 考勤记录
     * @return 考勤记录
     */
    @Override
    public List<AttendanceInfo> selectAttendanceInfoList(AttendanceInfo attendanceInfo) {
        return attendanceInfoMapper.selectAttendanceInfoList(attendanceInfo);
    }

    /**
     * 学生查询所有选课老师发布的考勤列表
     *
     * @param attendanceInfo 考勤记录
     * @return 考勤记录集合
     */
    @Override
    public List<AttendanceInfo> selectAttendanceInfoListForStudent(AttendanceInfo attendanceInfo) {
        return attendanceInfoMapper.selectAttendanceInfoListForStudent(attendanceInfo);
    }

    /**
     * 根据courseRecordId在sign_record表中查询签到状态
     *
     * @param courseRecordId
     * @return
     */
    @Override
    public Integer selectSignStatusByCourseRecordId(Long courseRecordId, Long userId) {
        return attendanceInfoMapper.selectSignStatusByCourseRecordIdAndUserId(courseRecordId, userId);
    }

    /**
     * 新增考勤记录
     *
     * @param attendanceInfo 考勤记录
     * @return 结果
     */
    @Override
    public int insertAttendanceInfo(AttendanceInfo attendanceInfo) {
        attendanceInfo.setCreateTime(DateUtils.getNowDate());
        AttendanceTime attendanceTime = AttendanceTime.getAttendanceTimeByCode(attendanceInfo.getAttendanceTime());
        // 获取签到时长
        Integer duration = attendanceTime.getInfo();
        log.info("「发布考勤定时任务开始」当前时间{}, 倒计时{}分钟, 更新考勤状态和学生签到情况", DateUtils.getNowDate(), duration);

        // 安排任务
        scheduler.schedule(() -> {
            // 调用executeAttendanceTimeout()自定义方法
            executeAttendanceTimeout(attendanceInfo.getCourseRecordId(), attendanceInfo.getCourseId(), duration);
        }, duration, TimeUnit.MINUTES);


        return attendanceInfoMapper.insertAttendanceInfo(attendanceInfo);
    }

    @Transactional
    public void executeAttendanceTimeout(Long courseRecordId, Long courseId, Integer duration) {

        log.info("「发布考勤定时任务结束」当前时间{}, 倒计时{}分钟, 更新考勤状态和学生签到情况", DateUtils.getNowDate(), duration);
        // 考勤过期 未签到考生签到状态赋值为未签到；考勤信息表结束状态改为1

        // 根据 courseRecordId 修改 attendance_info 表的 end_type 为 1
        AttendanceInfo attendanceInfo = new AttendanceInfo();
        attendanceInfo.setCourseRecordId(courseRecordId);
        attendanceInfo.setEndType(1L);
        attendanceInfoService.updateAttendanceInfo(attendanceInfo);

        // 获取到所有未签到的userId, deptId列表
        UnsignedRecord unsignedRecord = new UnsignedRecord();
        unsignedRecord.setCourseId(courseId);
        unsignedRecord.setCourseRecordId(courseRecordId);
        List<UnsignedRecord> unsignedRecords = unsignedRecordMapper.selectUnsignedRecordList(unsignedRecord);

        // 创建 SignRecord 列表
        List<SignRecord> signRecords = new ArrayList<>();
        SignStatus signStatus = SignStatus.NOT_SIGNED;  // 签到状态为未签
        // 使用 BeanUtils 复制属性
        for (UnsignedRecord unsigned : unsignedRecords) {
            SignRecord signRecord = new SignRecord();
            try {
                if(unsigned.getSignStatus() == null){
                    BeanUtils.copyProperties(signRecord, unsigned);
                    signRecord.setCourseRecordId(courseRecordId);   // 设置课程记录 ID
                    signRecord.setSignStatus(signStatus.getCode()); // 设置签到状态为未签
                }
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (InvocationTargetException e) {
                throw new RuntimeException(e);
            }
            if(signRecord.getSignStatus() == signStatus.getCode()){
                signRecords.add(signRecord);
            }
        }
        signRecordMapper.insertSignRecords(signRecords);
        log.info("批量插入{}条未签记录", signRecords.size());
    }


    /**
     * 修改考勤记录
     *
     * @param attendanceInfo 考勤记录
     * @return 结果
     */
    @Override
    public int updateAttendanceInfo(AttendanceInfo attendanceInfo) {
        return attendanceInfoMapper.updateAttendanceInfo(attendanceInfo);
    }

    /**
     * 批量删除考勤记录
     *
     * @param attendanceIds 需要删除的考勤记录主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteAttendanceInfoByAttendanceIds(Long[] attendanceIds) {
        int deletedCount = 0;
        int totalDeletedSignRecords = 0;
        for (Long attendanceId : attendanceIds) {
            // 根据 attendanceId 查询课程记录 Id
            Long courseRecordId = attendanceInfoMapper.selectCourseIdByAttendanceId(attendanceId);
            if (courseRecordId != null) {
                // 调用删除方法删除考勤记录
                int result = attendanceInfoMapper.deleteAttendanceInfoByAttendanceId(attendanceId);
                if (result > 0) { // 可以删除该考勤记录
                    // 根据课程记录ID删除sign_record里的学生考勤记录
                    int deletedSignRecords = signRecordMapper.deleteSignRecordsByCourseRecordId(courseRecordId);
                    totalDeletedSignRecords += deletedSignRecords;
                    log.info("成功删除考勤记录，考勤记录 ID: {}, 删除的学生考勤记录数量: {}", attendanceId, deletedSignRecords);
                }
                deletedCount += result;
            }
        }
        log.info("总共删除的考勤记录数量: {}, 总共删除的学生考勤记录数量: {}", deletedCount, totalDeletedSignRecords);
        return deletedCount;
    }

    /**
     * 删除考勤记录信息
     *
     * @param attendanceId 考勤记录主键
     * @return 结果
     */
    @Override
    public int deleteAttendanceInfoByAttendanceId(Long attendanceId) {
        return attendanceInfoMapper.deleteAttendanceInfoByAttendanceId(attendanceId);
    }

    /**
     * 获取考勤记录结束状态 By courseRecordId
     *
     * @param courseId 课程ID，由此获取courseRecordId
     * @return 0：未结束，1：已结束
     */
    @Override
    public Integer selectAttendanceInfoEndTypeByCourseRecordId(Long courseId) {
        CourseRecord courseRecord = courseRecordService.getStartCourseRecordByCourseId(courseId);
        Long courseRecordId = courseRecord.getId();
        return attendanceInfoMapper.selectAttendanceInfoEndTypeByCourseRecordId(courseRecordId);
    }
}
